/* eslint-disable @typescript-eslint/explicit-function-return-type */
import { useState, useEffect, useCallback, useMemo, useRef } from 'react'
import { toast } from 'sonner'
import { useConfig } from '@/context/config-context'

// UI组件导入
import { Button } from '@/components/ui/button'
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
import { Input } from '@/components/ui/input'
import { Label } from '@/components/ui/label'
import { Progress } from '@/components/ui/progress'
import { RadioGroup, RadioGroupItem } from '@/components/ui/radio-group'
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
import FileSelector from '@/components/ui/FileSelector'

// 类型定义
type CoordinateSystemType = 'EPSG:3857' | 'EPSG:4326'
type DownloadMethodType = 'geojson' | 'bbox'
type ProcessStateType = 'IDLE' | 'RUNNING' | 'EXITED' | 'CRASHED'

interface BboxState {
  minLon: string
  minLat: string
  maxLon: string
  maxLat: string
}

interface OutputInfoState {
  fileName: string
  outputDir: string
}

const ElevationDownloader = () => {
  // 配置相关状态
  const { config, updateConfig, saveConfig } = useConfig()

  // 界面输入状态
  const [coordinateSystem, setCoordinateSystem] = useState<CoordinateSystemType>('EPSG:3857')
  const [outputCoordinateSystem, setOutputCoordinateSystem] =
    useState<CoordinateSystemType>('EPSG:4326')
  const [bbox, setBbox] = useState<BboxState>({
    minLon: '',
    minLat: '',
    maxLon: '',
    maxLat: ''
  })
  const [geojsonPath, setGeojsonPath] = useState<string | null>(null)
  const [outputInfo, setOutputInfo] = useState<OutputInfoState>({
    fileName: '',
    outputDir: ''
  })

  // 下载状态
  const [isLoading, setIsLoading] = useState(false)
  const [downloadProgress, setDownloadProgress] = useState<string>('准备下载')
  const [downloadPercent, setDownloadPercent] = useState<number>(0)
  const [showProgress, setShowProgress] = useState(false) // 新增状态控制进度条显示

  // 模拟进度相关
  const [isSimulating, setIsSimulating] = useState(false)
  const simulationIntervalRef = useRef<number | null>(null)
  const lastRealProgressRef = useRef<number>(0)

  // 模拟进度函数
  const startProgressSimulation = useCallback(() => {
    if (simulationIntervalRef.current) {
      window.clearInterval(simulationIntervalRef.current)
    }

    setIsSimulating(true)
    lastRealProgressRef.current = 0

    // 重置进度为初始值
    setDownloadPercent(1)

    // 创建模拟进度更新间隔
    simulationIntervalRef.current = window.setInterval(() => {
      setDownloadPercent((prev) => {
        // 确保模拟进度不会超过95%且不会超过实际进度
        const realProgress = lastRealProgressRef.current

        if (realProgress > 0) {
          // 如果有实际进度，模拟值不应超过实际值
          return realProgress
        }

        if (prev >= 95) {
          return prev // 保持在95%
        }

        // 根据当前进度阶段动态调整增量速率
        let increment = 0
        if (prev < 30) {
          // 初始阶段快速增长
          increment = Math.random() * 1.5 + 0.5
        } else if (prev < 60) {
          // 中间阶段中等速度增长
          increment = Math.random() * 1 + 0.3
        } else if (prev < 85) {
          // 后期缓慢增长
          increment = Math.random() * 0.5 + 0.1
        } else {
          // 接近95%时非常缓慢
          increment = Math.random() * 0.2 + 0.05
        }

        return Math.min(95, prev + increment)
      })
    }, 500) // 每500毫秒更新一次模拟进度
  }, [])

  // 停止模拟进度
  const stopProgressSimulation = useCallback(() => {
    if (simulationIntervalRef.current) {
      window.clearInterval(simulationIntervalRef.current)
      simulationIntervalRef.current = null
    }
    setIsSimulating(false)
  }, [])

  // 处理过程状态变化
  const handleProcessStateChange = useCallback(
    (_event, state: ProcessStateType) => {
      switch (state) {
        case 'IDLE':
          setDownloadProgress('准备下载')
          setIsLoading(false)
          setDownloadPercent(0)
          setShowProgress(false) // 隐藏进度条
          stopProgressSimulation()
          break
        case 'RUNNING':
          setDownloadProgress('下载中...')
          setIsLoading(true)
          setShowProgress(true) // 显示进度条
          startProgressSimulation() // 启动模拟进度
          break
        case 'EXITED':
          setDownloadProgress('下载完成')
          setIsLoading(false)
          stopProgressSimulation() // 停止模拟
          setDownloadPercent(100)

          // 显示完成状态2秒后隐藏进度条
          setTimeout(() => {
            setShowProgress(false)
            setDownloadPercent(0)
          }, 2000)

          toast.success('高程数据下载完成')
          break
        case 'CRASHED':
          setDownloadProgress('下载失败')
          setIsLoading(false)
          stopProgressSimulation() // 停止模拟
          setShowProgress(false) // 隐藏进度条
          toast.error('下载过程中发生错误')
          break
      }
    },
    [startProgressSimulation, stopProgressSimulation]
  )

  // 处理下载进度更新
  const handleDownloadProgress = useCallback(
    (_event, percent: number) => {
      // 记录实际进度
      lastRealProgressRef.current = percent

      // 如果收到真实进度，显示真实进度
      if (percent > 0) {
        setDownloadPercent(percent)
        setDownloadProgress(`下载中 ${percent}%`)

        // 如果进度接近100%，可以停止模拟
        if (percent >= 99) {
          stopProgressSimulation()
        }
      }
    },
    [stopProgressSimulation]
  )

  // 确保组件卸载时清除模拟定时器
  useEffect(() => {
    return () => {
      if (simulationIntervalRef.current) {
        window.clearInterval(simulationIntervalRef.current)
      }
    }
  }, [])

  // 事件监听设置
  useEffect(() => {
    const removeStateListener = window.electron.ipcRenderer.on(
      'process-state-changed',
      handleProcessStateChange
    )

    const removeProgressListener = window.electron.ipcRenderer.on(
      'download-progress',
      handleDownloadProgress
    )

    return () => {
      removeStateListener()
      removeProgressListener()
    }
  }, [handleProcessStateChange, handleDownloadProgress])

  // 界面交互处理函数
  const handleBboxChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const { name, value } = e.target
    setBbox((prev) => ({ ...prev, [name]: value }))
  }, [])

  const handleFileNameChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    setOutputInfo((prev) => ({ ...prev, fileName: e.target.value }))
  }, [])

  const handleFolderSelect = useCallback(async () => {
    try {
      const path = (await window.api.SelectFolder()) as string
      if (path) {
        setOutputInfo((prev) => ({ ...prev, outputDir: path }))
      }
    } catch (error) {
      toast.error('选择文件夹失败')
      console.error('Folder selection error:', error)
    }
  }, [])

  const handleGeojsonSelect = useCallback(async () => {
    try {
      const path = (await window.api.SelectGeojsonFile()) as string
      if (path) {
        setGeojsonPath(path)
      }
    } catch (error) {
      toast.error('选择矢量文件失败')
      console.error('GeoJSON selection error:', error)
    }
  }, [])

  // 辅助函数
  const getCoordinatePlaceholder = useCallback(
    (type: string) => {
      const placeholders = {
        'EPSG:3857': {
          minLon: '例如: -11000000',
          minLat: '例如: 3000000',
          maxLon: '例如: -10000000',
          maxLat: '例如: 4000000'
        },
        'EPSG:4326': {
          minLon: '例如: 120.5',
          minLat: '例如: 30.5',
          maxLon: '例如: 121.5',
          maxLat: '例如: 31.5'
        }
      }

      return placeholders[coordinateSystem]?.[type as keyof BboxState] || ''
    },
    [coordinateSystem]
  )

  const outputPath = useMemo(() => {
    return outputInfo.outputDir ? `${outputInfo.outputDir}\\${outputInfo.fileName}.tif` : ''
  }, [outputInfo.outputDir, outputInfo.fileName])

  const downloadButtonText = useMemo(() => {
    return isLoading ? '正在下载中...' : '下载高程数据'
  }, [isLoading])

  // 验证表单输入
  const validateGeojsonForm = useCallback(() => {
    if (!geojsonPath) {
      toast.error('请选择矢量模型文件')
      return false
    }

    if (!outputInfo.fileName) {
      toast.error('请输入文件名')
      return false
    }

    if (!outputInfo.outputDir) {
      toast.error('请选择保存路径')
      return false
    }

    return true
  }, [geojsonPath, outputInfo.fileName, outputInfo.outputDir])

  const validateBboxForm = useCallback(() => {
    const { minLon, minLat, maxLon, maxLat } = bbox

    if (!minLon || !minLat || !maxLon || !maxLat) {
      toast.error('请填写完整的坐标范围')
      return false
    }

    if (!outputInfo.fileName) {
      toast.error('请输入文件名')
      return false
    }

    if (!outputInfo.outputDir) {
      toast.error('请选择保存路径')
      return false
    }

    // 验证坐标值的合理性
    if (parseFloat(minLon) >= parseFloat(maxLon) || parseFloat(minLat) >= parseFloat(maxLat)) {
      toast.error('坐标范围无效，请确保最大值大于最小值')
      return false
    }

    return true
  }, [bbox, outputInfo.fileName, outputInfo.outputDir])

  // 下载相关
  const startDownload = useCallback(
    async (method: DownloadMethodType) => {
      // 验证输入
      const isValid = method === 'geojson' ? validateGeojsonForm() : validateBboxForm()
      if (!isValid) return

      setIsLoading(true)
      setDownloadProgress('准备下载')
      setDownloadPercent(0)
      setShowProgress(true) // 确保显示进度条
      lastRealProgressRef.current = 0 // 重置实际进度记录

      try {
        const epsgValue = coordinateSystem === 'EPSG:4326' ? 4326 : 3857
        const output_epsgValue = outputCoordinateSystem === 'EPSG:4326' ? 4326 : 3857

        // 创建更新的配置对象
        const updatedConfig = {
          ...config,
          input_files: {
            ...config.input_files,
            dem_tif: outputPath,
            dsm_geo: geojsonPath ?? ''
          },
          ...(method === 'bbox' && {
            bbox: {
              minx: parseFloat(bbox.minLon),
              miny: parseFloat(bbox.minLat),
              maxx: parseFloat(bbox.maxLon),
              maxy: parseFloat(bbox.maxLat),
              epsg: epsgValue
            }
          }),
          download_output: {
            ...config.download_output,
            range_type: method === 'geojson' ? 1 : 2, // 1: geojson, 2: bbox
            target_epsg: output_epsgValue
          }
        }

        // 更新并保存配置
        await updateConfig(updatedConfig)
        await saveConfig()

        // 启动下载进程
        const result = await window.api.StartProcess('download_tif')
        if (!result) {
          throw new Error('启动下载进程失败')
        }
      } catch (error) {
        console.error('Download failed:', error)
        setIsLoading(false)
        setDownloadPercent(0)
        setShowProgress(false) // 出错时隐藏进度条
        stopProgressSimulation() // 确保出错时停止模拟
        toast.error(error instanceof Error ? error.message : '下载失败，请检查参数和网络连接')
      }
    },
    [
      bbox,
      config,
      coordinateSystem,
      outputCoordinateSystem,
      geojsonPath,
      outputPath,
      saveConfig,
      updateConfig,
      validateBboxForm,
      validateGeojsonForm,
      stopProgressSimulation
    ]
  )

  // UI渲染辅助函数
  const renderProgressIndicator = useMemo(() => {
    // 使用showProgress状态来控制显示
    if (!showProgress) return null

    return (
      <div className="mt-5 space-y-2">
        <div className="flex justify-between items-center text-sm">
          <span className="font-medium">
            {downloadProgress}
            {
              isSimulating && !lastRealProgressRef.current
              // && (
              //   <span className="text-muted-foreground ml-1">(模拟进度)</span>
              // )
            }
          </span>
          <span className="text-muted-foreground">{Math.round(downloadPercent)}%</span>
        </div>
        <Progress
          value={downloadPercent}
          className={`h-2 ${isSimulating && !lastRealProgressRef.current ? 'animate-pulse' : ''}`}
        />
      </div>
    )
  }, [showProgress, downloadProgress, downloadPercent, isSimulating])

  const isGeojsonFormValid = useMemo(
    () => !!geojsonPath && !!outputInfo.fileName && !!outputInfo.outputDir && !isLoading,
    [geojsonPath, outputInfo.fileName, outputInfo.outputDir, isLoading]
  )

  const isBboxFormValid = useMemo(
    () =>
      !!bbox.minLon &&
      !!bbox.minLat &&
      !!bbox.maxLon &&
      !!bbox.maxLat &&
      !!outputInfo.fileName &&
      !!outputInfo.outputDir &&
      !isLoading,
    [bbox, outputInfo.fileName, outputInfo.outputDir, isLoading]
  )

  const renderGeojsonTab = (
    <div className="grid w-full items-center gap-5">
      <FileSelector
        id="geojson-file"
        label="选择矢量模型："
        value={geojsonPath}
        onChange={setGeojsonPath}
        onSelectFile={handleGeojsonSelect}
      />
      <div className="space-y-2">
        <Label htmlFor="fileName" className="block">
          文件名：
        </Label>
        <Input
          id="fileName"
          placeholder="请输入文件名"
          value={outputInfo.fileName}
          onChange={handleFileNameChange}
          className="w-full"
        />
      </div>

      <div className="space-y-2">
        <Label className="block">输出坐标系</Label>
        <RadioGroup
          defaultValue="EPSG:4326"
          value={outputCoordinateSystem}
          onValueChange={(value) => setOutputCoordinateSystem(value as CoordinateSystemType)}
          className="flex space-x-4"
        >
          <div className="flex items-center space-x-2">
            <RadioGroupItem value="EPSG:4326" id="output-epsg4326" />
            <Label htmlFor="output-epsg4326" className="cursor-pointer">
              EPSG:4326 (WGS84)
            </Label>
          </div>
          <div className="flex items-center space-x-2">
            <RadioGroupItem value="EPSG:3857" id="output-epsg3857" />
            <Label htmlFor="output-epsg3857" className="cursor-pointer">
              EPSG:3857 (Web Mercator)
            </Label>
          </div>
        </RadioGroup>
      </div>

      <FileSelector
        id="output-dir"
        label="保存路径："
        placeholder="请点击选择文件夹"
        value={outputPath}
        onChange={(path) => setOutputInfo((prev) => ({ ...prev, outputDir: path }))}
        onSelectFile={handleFolderSelect}
      />
      {renderProgressIndicator}
      <Button
        className="w-full mt-2"
        disabled={!isGeojsonFormValid}
        onClick={() => startDownload('geojson')}
      >
        {downloadButtonText}
      </Button>
    </div>
  )

  const renderBboxTab = (
    <div className="grid w-full items-center gap-5">
      <div className="mb-4">
        <Label className="mb-2 block">选择坐标系统</Label>
        <RadioGroup
          defaultValue="EPSG:3857"
          value={coordinateSystem}
          onValueChange={(value) => setCoordinateSystem(value as CoordinateSystemType)}
          className="flex space-x-4"
        >
          <div className="flex items-center space-x-2">
            <RadioGroupItem value="EPSG:3857" id="epsg3857" />
            <Label htmlFor="epsg3857" className="cursor-pointer">
              EPSG:3857 (Web Mercator)
            </Label>
          </div>
          <div className="flex items-center space-x-2">
            <RadioGroupItem value="EPSG:4326" id="epsg4326" />
            <Label htmlFor="epsg4326" className="cursor-pointer">
              EPSG:4326 (WGS84)
            </Label>
          </div>
        </RadioGroup>
      </div>

      <div className="grid grid-cols-2 gap-4">
        <div className="space-y-2">
          <Label htmlFor="minLon">最小经度</Label>
          <Input
            id="minLon"
            name="minLon"
            placeholder={getCoordinatePlaceholder('minLon')}
            value={bbox.minLon}
            onChange={handleBboxChange}
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="minLat">最小纬度</Label>
          <Input
            id="minLat"
            name="minLat"
            placeholder={getCoordinatePlaceholder('minLat')}
            value={bbox.minLat}
            onChange={handleBboxChange}
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="maxLon">最大经度</Label>
          <Input
            id="maxLon"
            name="maxLon"
            placeholder={getCoordinatePlaceholder('maxLon')}
            value={bbox.maxLon}
            onChange={handleBboxChange}
          />
        </div>
        <div className="space-y-2">
          <Label htmlFor="maxLat">最大纬度</Label>
          <Input
            id="maxLat"
            name="maxLat"
            placeholder={getCoordinatePlaceholder('maxLat')}
            value={bbox.maxLat}
            onChange={handleBboxChange}
          />
        </div>
      </div>
      <div className="space-y-2">
        <Label htmlFor="fileName">文件名</Label>
        <Input
          id="fileName"
          placeholder="高程数据"
          value={outputInfo.fileName}
          onChange={handleFileNameChange}
          className="w-full"
        />
      </div>

      <div className="space-y-2">
        <Label className="block">输出坐标系</Label>
        <RadioGroup
          defaultValue="EPSG:4326"
          value={outputCoordinateSystem}
          onValueChange={(value) => setOutputCoordinateSystem(value as CoordinateSystemType)}
          className="flex space-x-4"
        >
          <div className="flex items-center space-x-2">
            <RadioGroupItem value="EPSG:4326" id="epsg4326" />
            <Label htmlFor="epsg4326" className="cursor-pointer">
              EPSG:4326 (WGS84)
            </Label>
          </div>
          <div className="flex items-center space-x-2">
            <RadioGroupItem value="EPSG:3857" id="epsg3857" />
            <Label htmlFor="epsg3857" className="cursor-pointer">
              EPSG:3857 (Web Mercator)
            </Label>
          </div>
        </RadioGroup>
      </div>

      <FileSelector
        id="output-dir"
        label="保存路径："
        placeholder="请点击选择文件夹"
        value={outputPath}
        onChange={(path) => setOutputInfo((prev) => ({ ...prev, outputDir: path }))}
        onSelectFile={handleFolderSelect}
      />
      {renderProgressIndicator}
      <Button
        className="w-full mt-2"
        disabled={!isBboxFormValid}
        onClick={() => startDownload('bbox')}
      >
        {downloadButtonText}
      </Button>
    </div>
  )

  // 主渲染
  return (
    <Card className="w-full shadow-md">
      <CardHeader className="bg-slate-50 dark:bg-slate-900">
        <CardTitle>高程数据下载</CardTitle>
        <CardDescription>通过矢量模型文件或坐标边界下载高程数据</CardDescription>
      </CardHeader>
      <CardContent className="pt-6">
        <Tabs defaultValue="geojson">
          <TabsList className="grid w-full grid-cols-2 mb-6">
            <TabsTrigger value="geojson">矢量模型文件</TabsTrigger>
            <TabsTrigger value="bbox">坐标边界</TabsTrigger>
          </TabsList>
          <TabsContent value="geojson">{renderGeojsonTab}</TabsContent>
          <TabsContent value="bbox">{renderBboxTab}</TabsContent>
        </Tabs>
      </CardContent>
    </Card>
  )
}

export default ElevationDownloader
